home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * Language : Turbo C 2.0
- * Logfile : sz.c
- * Project : Comms library.
- * Date : 24 Jan 90
- * Revision : 1.1 GT PC version.
- * 07 Mar 90 : 1.2 GT Background transfer.
- * 25 Oct 92 : 1.3 GT Mods for KA9Q.
- * 30 Jan 93 : 1.4 GT Fix KA9Q background working.
- * 21 Feb 93 : 1.5 GT Fix reporting.
- * 08 May 93 : 1.6 GT Fix warnings.
- * 24 Jan 94 : 1.7 GT _flush -> _rbsb_flush.
- *****************************************************************************
- * Purpose : File send driver.
- *****************************************************************************
- * : This module is based on the equivalent module in the
- * : 31 Aug 87 version of rz/sz.
- * $Id: sz.c 1.5 94/01/26 13:55:15 ROOT_DOS Exp $
- *
- * ATARI Version by David Nash - dnash@chaos.demon.co.uk
- *
- ****************************************************************************/
-
- #include <io.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <time.h>
- #include <process.h>
- #include <string.h>
- #include <io.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <dos.h>
- #ifdef ATARI
- #include <ext.h>
- #endif
- #include "config.h"
- #include "socket.h"
- #include "proc.h"
-
- /* kludge for krappy Microsoft */
-
- #ifndef S_IFBLK
- #define S_IFBLK 0x3000
- #endif
-
- #include "zmodem.h"
- #include "sz.h"
- #include "rbsb.h" /* most of the system dependent stuff here */
- #include "zm.h"
- #ifdef DEBUGZ
- #include "tty.h"
- #endif
-
-
- #define HOWMANY 2048
- #define NO_DCD 1
-
- /****************************************************************************
- * Local prototypes. *
- ****************************************************************************/
-
- #if 0
- static void bibi (int n);
- #endif
- static void chkinvok (char protocol);
- static int readline (int n);
- static void purgeline (void);
- #if 0
- static void onintr (void);
- #endif
- static int wcsend (int argc, char **argp);
- static int wcs (char *oname);
- static int wctxpn (char *name);
- static int getnak (void);
- static int wctx (long flen);
- static int wcputsec (char *buf, int sectnum, int cseclen);
- static int filbuf (char *buf, int count);
- static int zfilbuf (char *buf, int count);
- static int readock (int timeout, int count);
- static int getzrxinit (void);
- static int sendzsinit (void);
- static int zsendfile (char *buf, int blen);
- static int zsendfdata (void);
- static int getinsync (int flag);
- static void saybibi (void);
- static int zsendcmd (char *buf, int blen);
-
-
- /****************************************************************************
- * Global data. *
- ****************************************************************************/
-
- int _Zmodem = 0; /* ZMODEM protocol requested */
- unsigned _Baud_z = 19200;
- static unsigned Txwindow; /* Control the size of the transmitted window */
- static unsigned Txwspac; /* Spacing between zcrcq requests */
- static unsigned Txwcnt; /* Counter used to space ack requests */
- static long Lrxpos; /* Receiver's last reported offset */
- int _errors;
- int _sending; /* TRUE - sending a file. */
- int _zperr_handle; /* -> log file */
-
- /*
- * Attention string to be executed by receiver to interrupt streaming data
- * when an error is detected. A pause (0336) may be needed before the
- * ^C (03) or after it.
- */
-
- static char Myattn[] = { 0 };
-
- static int in;
-
- int _Lastrx; /* was char */
- int _Crcflg; /* was char */
- int _Wcsmask = 0377;
-
- /* Command line option flags */
-
- int _Verbose = 0;
- static int Modem2 = 0; /* XMODEM Protocol - don't send pathnames */
- int _Quiet = 0; /* overrides logic that would otherwise set
- verbose */
- static int Ascii = 0; /* Add CR's for brain damaged programs */
- static int Fullname = 0; /* transmit full pathname */
- static int Unlinkafter = 0; /* Unlink file after it is sent */
-
- static int Dottoslash = 0; /* Change foo.bar.baz to foo/bar/baz */
- int _firstsec;
- static int errcnt = 0; /* number of files unreadable */
- static int blklen = SECSIZ; /* length of transmitted records */
- static int Optiong; /* Let it rip no wait for sector ACK's */
- static int Noeofseen;
- static int Totsecs; /* total number of sectors this file */
- static char txbuf[KSIZE];
- static int Filcnt = 0; /* count of number of files opened */
- static int Lfseen = 0;
- static unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
- static int Tframlen = 0; /* Override for tx frame length */
- static int blkopt = 0; /* Override value for zmodem blklen */
- static int Rxflags = 0;
- static long bytcnt;
- static int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
- static char Lzconv; /* Local ZMODEM file conversion request */
- char _Lzmanag; /* Local ZMODEM file management request */
- static int Lskipnocor;
- static char Lztrans;
- char _zconv; /* ZMODEM file conversion request */
- char _zmanag; /* ZMODEM file management request */
- char _ztrans; /* ZMODEM file transport request */
- static int Command; /* Send a command, then exit. */
- static char Cmdstr[256]; /* Command string */
- static int Cmdtries = 11;
- static int Cmdack1; /* Rx ACKs command, then do it */
- static int Exitcode;
- static int Testattn; /* Force receiver to send Attn, etc with qbf. */
- static char *qbf = "The quick brown fox jumped over the lazy dog's back "
- "1234567890\r\n";
- static long Lastread; /* Beginning offset of last buffer read */
- static int Lastn; /* Count of last buffer read or -1 */
- static int Dontread; /* Don't read the buffer, it's still there */
- static long Lastsync; /* Last offset to which we got a ZRPOS */
- static int Beenhereb4; /* How many times we've been ZRPOS'd same
- place */
-
- jmp_buf _tohere; /* For user abort. */
- static jmp_buf intrjmp; /* For the interrupt on RX CAN. */
- jmp_buf _nocarrier; /* For carrier dropped. */
-
- int _Zctlesc; /* Encode control characters */
- int _Nozmodem = 0; /* If invoked as "sb" */
- int _Zrwindow = 1400; /* RX window size (controls garbage count) */
- void (*_do_report) (int type, void *data) = _zperr;
- /* -> progress report fn */
-
- extern int Lleft; /* number of chars in read buffer */
- extern int Readnum; /* how many bytes to read */
-
-
- #if 0
- /****************************************************************************
- * bibi *
- * Called by signal interrupt or terminate to clean things up. *
- ****************************************************************************/
-
- static void bibi (int n)
- {
- n = n;
- _canit ();
- _zperr_ ("Interrupted\n");
- longjmp (_tohere, -1);
- } /* static void bibi (int n) */
-
-
- /****************************************************************************
- * onintr *
- * Called when Zmodem gets an interrupt (^X). *
- ****************************************************************************/
-
- static void onintr (void)
- {
- #if 0
- signal (SIGINT, SIG_IGN);
- #endif
- longjmp (intrjmp, -1);
- } /* static void onintr (void) */
- #endif
-
-
- /****************************************************************************
- * _no_carrier *
- * Tests to see if CD still present, exits if not. *
- ****************************************************************************/
-
- void _no_carrier (void)
- {
- #if !defined (NO_DCD)
- if ((modemstat () & 0x80) == 0)
- {
- _zperr_ ("No carrier\n");
- longjmp (_nocarrier, -1);
- }
-
- #endif
- } /* void _no_carrier (void) */
-
-
- /****************************************************************************
- * _sendline and _xsendline *
- * Send a character to remote. *
- ****************************************************************************/
-
- void _sendline (int c)
- {
- if (_sending)
- c &= _Wcsmask;
-
- _xsendline (c);
- } /* void _sendline (int c) */
-
-
- void _xsendline (int c)
- {
- #ifdef DEBUGZ
- if (_Verbose > 6)
- _vfile ("_xsendline: %x\n", c);
- #endif
-
- while (_send ((unsigned char *) &c, 1) != 1)
- _no_carrier ();
-
- } /* void _xsendline (int c) */
-
-
- /****************************************************************************
- * _flushmo *
- * Flush the ouput channel. *
- ****************************************************************************/
-
- void _flushmo (void)
- {
- _rbsb_flush ();
- } /* void _flushmo (void) */
-
-
- /****************************************************************************
- * _sendfile *
- * Send file(s). Returns 0 if successful. *
- ****************************************************************************/
-
- int _sendfile (int s, char protocol, char *options, char *filenames[],
- void (*reporter) (int type, void *data))
- {
- char *cp;
- int npats;
- int agcnt;
- char **agcv;
- char **patts;
- int i; /* loop counter */
- #if 0
- void (*sigint_sav) (int);
- void (*sigterm_sav) (int);
- #endif
-
- /* Initialise global variables */
-
- _z_socket = s;
- Lleft = 0;
- Readnum = HOWMANY;
- Ascii = 0;
- blklen = SECSIZ;
- blkopt = 0;
- Cmdtries = 11;
- Command = FALSE;
- _do_report = _zperr;
- Dottoslash = 0;
- errcnt = 0;
- Exitcode = 0;
- Filcnt = 0;
- Fullname = 0;
- Lfseen = 0;
- Modem2 = 0;
- _Nozmodem = 0;
- _Quiet = 0;
- Rxbuflen = 16384;
- Rxflags = 0;
- _sending = TRUE;
- Tframlen = 0;
- Unlinkafter = 0;
- Wantfcs32 = TRUE;
- _Wcsmask = 0377;
- _Verbose = 0;
- _Zmodem = 0;
- _Zrwindow = 1400;
-
- /* See if null padding required */
-
- if (((cp = getenv ("ZNULLS")) != NULL) && *cp)
- _Znulls = atoi (cp);
-
- chkinvok (protocol); /* select protocol */
- _Rxtimeout = 600;
- npats = 0;
-
- /* Parse options. */
-
- cp = options;
- while (*cp != '\0')
- {
- switch (*cp++)
- {
- case '+': /* append file */
- _Lzmanag = ZMAPND;
- break;
-
- case '7': /* strip top bit */
- _Wcsmask = 0177;
- break;
-
- case 'a': /* NL -> CRNL conversion */
- Lzconv = ZCNL;
- Ascii = TRUE;
- break;
-
- case 'b': /* binary file */
- Lzconv = ZCBIN;
- break;
-
- case 'i': /* command, no wait */
- Cmdack1 = ZCACK1;
-
- /* **** FALL THROUGH TO **** */
-
- case 'c': /* command, wait */
- if (*cp != '#') /* command delimiter? */
- return (ERROR); /* invalid parameter */
-
- Command = TRUE;
- for (i = 0; i < sizeof (Cmdstr); i++)
- {
- if (*++cp == '#')
- break; /* end of command */
-
- Cmdstr[i] = *cp;
- }
-
- Cmdstr[i] = '\0';
- cp++;
- break;
-
- case 'd': /* . -> / */
- ++Dottoslash;
-
- /* **** FALL THROUGH TO **** */
-
- case 'f': /* full pathnames */
- Fullname = TRUE;
- break;
-
- case 'e': /* escape ctl chars */
- _Zctlesc = 1;
- break;
-
- case 'k': /* YMODEM 1k */
- blklen = KSIZE;
- break;
-
- case 'L': /* limit subpacket length */
- sscanf (cp, "%d", &blkopt);
- if (blkopt < 24 || blkopt > 1024)
- return (ERROR); /* bad length */
-
- cp = _stbnb (cp); /* skip whitespace */
- break;
-
- case 'l': /* limit frame length */
- sscanf (cp, "%d", &Tframlen);
- if (Tframlen < 32 || Tframlen > 1024)
- return (ERROR);
-
- cp = _stbnb (cp);
- break;
-
- case 'N': /* source newer or longer */
- _Lzmanag = ZMNEWL;
- break;
-
- case 'n': /* source newer */
- _Lzmanag = ZMNEW;
- break;
-
- case 'o': /* 16 bit CRC */
- Wantfcs32 = FALSE;
- break;
-
- case 'p': /* no target overwrite */
- _Lzmanag = ZMPROT;
- break;
-
- case 'r': /* resume file transfer */
- Lzconv = ZCRESUM;
- break;
-
- case 'q': /* quiet */
- _Quiet = TRUE;
- _Verbose = 0;
- break;
-
- case 't': /* change timeout */
- sscanf (cp, "%d", &_Rxtimeout);
- if (_Rxtimeout < 10 || _Rxtimeout > 1000)
- return (ERROR);
-
- cp = _stbnb (cp);
- break;
-
- case 'T': /* test attention mode */
- Testattn = TRUE;
- break;
-
- case 'u': /* erase after send */
- ++Unlinkafter;
- break;
-
- case 'v': /* debugging info */
- ++_Verbose;
- break;
-
- case 'w': /* window size */
- sscanf (cp, "%d", &Txwindow);
- if (Txwindow < 256)
- Txwindow = 256;
-
- Txwindow = (Txwindow / 64) * 64;
- Txwspac = Txwindow / 4;
- if (blkopt > Txwspac || (!blkopt && Txwspac < 1024))
- blkopt = Txwspac;
-
- cp = _stbnb (cp);
- break;
-
- case 'X': /* use XMODEM */
- ++Modem2;
- break;
-
- case 'Y': /* overwrite target only if
- present */
- Lskipnocor = TRUE;
-
- /* **** FALL THROUGH TO **** */
-
- case 'y': /* overwrite target always */
- _Lzmanag = ZMCLOB;
- break;
-
- default:
- return (ERROR);
- } /* switch (*cp++) */
-
- } /* while (*cp != '\0') */
-
- /* parse filenames */
-
- patts = filenames;
- while (**patts != '\0')
- {
- npats++; /* bump filename count */
- patts++; /* try next string */
- }
-
- patts = filenames;
- if (npats < 1 && !Command)
- return (ERROR); /* no filenames */
-
- /* Get reporter function */
-
- if (reporter != NULL)
- _do_report = reporter; /* user supplied fn */
-
- #if 0
- if (_Verbose)
- {
- if ((_zperr_handle = open (LOGFILE,
- O_CREAT | O_APPEND | O_WRONLY | O_TEXT,
- S_IFREG | S_IWRITE)) == -1)
- {
- char buff[80];
-
- sprintf (buff, "Can't open log file %s: %s\n",
- LOGFILE, strerror (errno));
- (*_do_report) (2, buff);
- (*_do_report) (3, &Filcnt); /* report no of files */
-
- return (ERROR);
- }
-
- _do_report = _zperr; /* use default reporter */
- }
- #endif
-
- if (!_Quiet)
- {
- if (_Verbose == 0)
- _Verbose = 2;
-
- }
-
- #if 0
- if ((sigint_sav = signal (SIGINT, bibi)) == SIG_IGN)
- signal (SIGINT, SIG_IGN);
- else
- signal (SIGINT, bibi);
-
- #endif
-
- #if 0
- sigint_sav = signal (SIGINT, bibi);
- sigterm_sav = signal (SIGTERM, bibi);
- #endif
-
- /* Organise escape routes. */
-
- if (setjmp (_tohere) != 0)
- {
- (*_do_report) (3, &Filcnt); /* report no of files */
- #if 0
- signal (SIGINT, sigint_sav);
- signal (SIGTERM, sigterm_sav);
- (void) close (_zperr_handle);
- #endif
- return (-2); /* user abort */
- }
-
- if (setjmp (_nocarrier) != 0)
- {
- (*_do_report) (3, &Filcnt); /* report no of files */
- #if 0
- signal (SIGINT, sigint_sav);
- signal (SIGTERM, sigterm_sav);
- (void) close (_zperr_handle);
- #endif
- return (-3); /* lost carrier */
- }
-
- if (!Modem2)
- {
- #if 0
- if (!_Nozmodem)
- {
- printf ("rz\r");
- }
- #endif
-
- if (!Command && !_Quiet && _Verbose != 1)
- {
- _say ("%d file%s requested:\r\n",
- npats, npats > 1 ? "s" : "");
- for (agcnt = npats, agcv = patts; --agcnt >= 0;)
- {
- _say ("%s ", *agcv++);
- }
-
- _say ("\r\n");
- _say ("\r\n\bSending in Batch Mode\r\n");
- }
-
- if (!_Nozmodem)
- {
- _stohdr (0L);
- if (Command)
- _Txhdr[ZF0] = ZCOMMAND;
-
- _zshhdr (ZRQINIT, _Txhdr);
- }
-
- } /* if (!Modem2) */
-
- if (Command)
- {
- if (getzrxinit ())
- {
- Exitcode = -2;
- _canit ();
- }
- else if (zsendcmd (Cmdstr, 1 + strlen (Cmdstr)))
- {
- Exitcode = -2;
- _canit ();
- }
-
- }
- else if (wcsend (npats, patts) == ERROR)
- {
- Exitcode = -2;
- _canit ();
- }
-
- if (!_Quiet)
- _say ("\n");
-
- (*_do_report) (3, &Filcnt); /* report no of files */
- #if 0
- signal (SIGINT, sigint_sav);
- signal (SIGTERM, sigterm_sav);
- (void) close (_zperr_handle);
- #endif
- return (Exitcode);
- } /* int _sendfile (int s, char protocol, char *options,
- char *filenames[],
- void (*reporter) (int type, void *data)) */
-
-
- /****************************************************************************
- * _stbnb *
- * Skip to blank then skip to nonblank. *
- ****************************************************************************/
-
- char *_stbnb (char *cp)
- {
- /* skip to blank */
-
- while (!isspace (*cp))
- cp++;
-
- /* skip to nonblank */
-
- while (isspace (*cp))
- cp++;
-
- return (cp);
- } /* char *_stbnb (char *cp) */
-
-
- /****************************************************************************
- * wcsend *
- * Send <argc> strings (<argp>) to remote. *
- ****************************************************************************/
-
- static int wcsend (int argc, char **argp)
- {
- int n;
-
- _Crcflg = FALSE;
- _firstsec = TRUE;
- bytcnt = -1;
- for (n = 0; n < argc; ++n)
- {
- Totsecs = 0;
- if (wcs (argp[n]) == ERROR)
- return ERROR;
-
- }
-
- Totsecs = 0;
- if (Filcnt == 0)
- {
- /* bitch if we couldn't open ANY files */
-
- #if 0
- if (1)
- #endif
- {
- Command = TRUE;
- strcpy (Cmdstr, "echo Can't open any requested files");
- if (getnak ())
- {
- Exitcode = -2;
- _canit ();
- }
-
- if (!_Zmodem)
- _canit ();
- else if (zsendcmd (Cmdstr, 1 + strlen (Cmdstr)))
- {
- Exitcode = -2;
- _canit ();
- }
-
- Exitcode = -2;
- return OK;
- }
-
- #if 0 /* unreachable */
- _canit ();
- _say ("\r\nCan't open any requested files.\r\n");
- return ERROR;
- #endif
- } /* if (Filcnt == 0) */
-
- if (_Zmodem)
- saybibi ();
- else if (!Modem2)
- wctxpn ("");
-
- return OK;
- } /* static int wcsend (int argc, char **argp) */
-
-
- /****************************************************************************
- * wcs *
- * Send file <oname> to remote. *
- ****************************************************************************/
-
- static int wcs (char *oname)
- {
- int c;
- struct stat f;
- char name[PATHLEN];
-
- strcpy (name, oname);
- if ((in = open (oname, O_RDONLY | O_BINARY, S_IREAD)) == -1)
- {
- if (_Verbose > 2)
- {
- _say ("Couldn't open %s\r\n", oname);
- }
-
- ++errcnt;
- return OK; /* pass over it, there may be others */
- }
-
- ++Noeofseen;
- Lastread = 0;
- Lastn = -1;
- Dontread = FALSE;
-
- /* Check for directory or block special files */
-
- fstat (in, &f);
- c = f.st_mode & S_IFMT;
- if (c == S_IFDIR || c == S_IFBLK)
- {
- close (in);
- return OK;
- }
-
- ++Filcnt;
- switch (wctxpn (name))
- {
- case ERROR:
- return ERROR;
-
- case ZSKIP:
- return OK;
- }
-
- if (!_Zmodem && wctx (f.st_size) == ERROR)
- return ERROR;
-
- if (Unlinkafter)
- unlink (oname);
-
- return 0;
- } /* static int wcs (char *oname) */
-
-
- /****************************************************************************
- * wctxpn *
- * Generate and transmit pathname block consisting of pathname (null *
- * terminated), file length, mode time and file mode in octal as provided *
- * by the fstat call. *
- * N.B.: modifies the passed name, may extend it! *
- ****************************************************************************/
-
- static int wctxpn (char *name)
- {
- char *p, *q;
- char name2[PATHLEN];
- struct stat f;
-
- (*_do_report) (0, name);
- if (Modem2)
- {
- if (*name && (fstat (in, &f) != -1))
- {
- _say ("Sending %s, %ld blocks: ", name, f.st_size >> 7);
- }
-
- _say ("Give your local XMODEM receive command now.\r\n");
- return OK;
- }
-
- _vfile ("Awaiting pathname nak for %s", *name ? name : "<END>");
- if (!_Zmodem)
- if (getnak ())
- return ERROR;
-
- q = (char *) 0;
- if (Dottoslash)
- {
- /* change . to . */
- for (p = name; *p; ++p)
- {
- if (*p == '/')
- q = p;
- else if (*p == '.')
- *(q = p) = '/';
-
- }
-
- if (q && strlen (++q) > 8)
- {
- /* If name > 8 chars */
- q += 8; /* make it .ext */
- strcpy (name2, q); /* save excess of name */
- *q = '.';
- strcpy (++q, name2); /* add it back */
- }
-
- } /* if (Dottoslash) */
-
- for (p = name, q = txbuf; *p;)
- if ((*q++ = *p++) == '\\' && !Fullname)
- q = txbuf;
-
- *q++ = 0;
- p = q;
- while (q < (txbuf + KSIZE))
- *q++ = 0;
-
- if (!Ascii && *name && fstat (in, &f) != -1)
- sprintf (p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
-
- /* force 1k blocks if name won't fit in 128 byte block */
-
- if (txbuf[125])
- blklen = KSIZE;
- else
- {
- /* A little goodie for IMP/KMD */
-
- if (_Zmodem)
- blklen = SECSIZ;
-
- txbuf[127] = (char) ((f.st_size + 127) >> 7);
- txbuf[126] = (char) ((f.st_size + 127) >> 15);
- }
-
- if (_Zmodem)
- return zsendfile (txbuf, (int) (1 + strlen (p) + (p - txbuf)));
-
- if (wcputsec (txbuf, 0, SECSIZ) == ERROR)
- return ERROR;
-
- return OK;
- } /* static int wctxpn (char *name) */
-
-
- /****************************************************************************
- * getnak *
- * Returns FALSE if NAK or ZPAD received. *
- ****************************************************************************/
-
- static int getnak (void)
- {
- int firstch;
-
- _Lastrx = 0;
- for (;;)
- {
- switch (firstch = readock (800, 1))
- {
- case ZPAD:
- if (getzrxinit ())
- return ERROR;
-
- Ascii = 0;
- return FALSE;
-
- case ZTIMEOUT:
- _zperr_ ("Timeout on pathname");
- return TRUE;
-
- case WANTG:
- Optiong = TRUE;
- blklen=KSIZE;
-
- case WANTCRC:
- _Crcflg = TRUE;
-
- case NAK:
- return FALSE;
-
- case CAN:
- if ((firstch = readock (20, 1)) == CAN && _Lastrx == CAN)
- return TRUE;
-
- default:
- break;
- } /* switch (firstch = readock (800, 1)) */
-
- _Lastrx = firstch;
- } /* for (;;) */
-
- } /* static int getnak (void) */
-
-
- /****************************************************************************
- * wctx *
- * Send <flen> bytes (in blocks) using XMODEM or YMODEM. *
- ****************************************************************************/
-
- static int wctx (long flen)
- {
- int thisblklen;
- int sectnum, attempts, firstch;
- long charssent;
-
- charssent = 0;
- _firstsec = TRUE;
- thisblklen = blklen;
- _vfile ("wctx:file length = %ld", flen);
-
- while ((firstch = readock (_Rxtimeout, 2)) != NAK &&
- firstch != WANTCRC &&
- firstch != WANTG &&
- firstch != ZTIMEOUT &&
- firstch != CAN)
- ;
-
- if (firstch == CAN)
- {
- _zperr_ ("Receiver CANcelled");
- return ERROR;
- }
-
- if (firstch == WANTCRC)
- _Crcflg = TRUE;
-
- if (firstch == WANTG)
- _Crcflg = TRUE;
-
- sectnum = 0;
- for (;;)
- {
- if (flen <= (charssent + 896L))
- thisblklen = 128;
-
- if (!filbuf (txbuf, thisblklen))
- break;
-
- if (wcputsec (txbuf, ++sectnum, thisblklen) == ERROR)
- return ERROR;
-
- charssent += thisblklen;
- }
-
- close (in);
- attempts = 0;
- do
- {
- purgeline ();
- _sendline (EOT);
- ++attempts;
- firstch = (readock (_Rxtimeout, 1));
- } while (firstch != ACK && attempts < RETRYMAX);
-
- if (attempts == RETRYMAX)
- {
- _zperr_ ("No ACK on EOT");
- return ERROR;
- }
- else
- return OK;
-
- } /* static int wctx (long flen) */
-
-
- /****************************************************************************
- * wcputsec *
- * Send block <sectnum> of length <cseclen> using XMODEM or YMODEM. *
- ****************************************************************************/
-
- static int wcputsec (char *buf, int sectnum, int cseclen)
- {
- int checksum, wcj;
- char *cp;
- unsigned oldcrc;
- int firstch;
- int attempts;
-
- firstch = 0; /* part of logic to detect CAN CAN */
-
- _vfile ("Sector %3d %2dk\n", Totsecs, Totsecs / 8 );
- if (_Verbose > 1)
- _say ("\rSector %3d %2dk ", Totsecs, Totsecs / 8 );
-
- for (attempts = 0; attempts <= RETRYMAX; attempts++)
- {
- _Lastrx = firstch;
- _sendline (cseclen == KSIZE ? STX : SOH);
- _sendline (sectnum);
- _sendline (- sectnum - 1);
- oldcrc = checksum = 0;
- for (wcj = cseclen, cp = buf; --wcj >= 0;)
- {
- _sendline (*cp);
- oldcrc = updcrc ((0377 & *cp), oldcrc);
- checksum += *cp++;
- }
-
- if (_Crcflg)
- {
- oldcrc = updcrc (0, updcrc (0, oldcrc));
- _sendline ((int) oldcrc >> 8);
- _sendline ((int) oldcrc);
- }
- else
- _sendline (checksum);
-
- if (Optiong)
- {
- _firstsec = FALSE;
- return OK;
- }
-
- firstch = readock (_Rxtimeout, (Noeofseen && sectnum) ? 2 : 1);
-
- gotnak:
- switch (firstch)
- {
- case CAN:
- if (_Lastrx == CAN)
- {
- cancan:
- _zperr_ ("Cancelled");
- return ERROR;
- }
-
- break;
-
- case ZTIMEOUT:
- _zperr_ ("Timeout on sector ACK");
- continue;
-
- case WANTCRC:
- if (_firstsec)
- _Crcflg = TRUE;
-
- case NAK:
- _zperr_ ("NAK on sector");
- continue;
-
- case ACK:
- _firstsec = FALSE;
- Totsecs += (cseclen >> 7);
- return OK;
-
- case ERROR:
- _zperr_ ("Got burst for sector ACK");
- break;
-
- default:
- _zperr_ ("Got %02x for sector ACK", firstch);
- break;
- } /* switch (firstch) */
-
- for (;;)
- {
- _Lastrx = firstch;
- if ((firstch = readock (_Rxtimeout, 2)) == ZTIMEOUT)
- break;
-
- if (firstch == NAK || firstch == WANTCRC)
- goto gotnak;
-
- if (firstch == CAN && _Lastrx == CAN)
- goto cancan;
-
- }
-
- } /* for (attempts = 0; attempts <= RETRYMAX; attempts++) */
-
- _zperr_ ("Retry Count Exceeded");
- return ERROR;
- } /* static int wcputsec (char *buf, int sectnum, int cseclen) */
-
-
- /****************************************************************************
- * filbuf *
- * Fill <buf> with <count> chars padding with ^Z for CPM. *
- ****************************************************************************/
-
- static int filbuf (char *buf, int count)
- {
- int c, m;
- char locbuf[BUFSIZ]; /* local read buffer */
- char *q; /* -> read buffer */
- int rcount; /* no of chars read */
-
- if (!Ascii)
- {
- m = read (in, buf, count);
- if (m <= 0)
- return 0;
-
- while (m < count)
- buf[m++] = 032;
-
- return count;
- }
-
- m = count;
- if (Lfseen)
- {
- *buf++ = 012;
- --m;
- Lfseen = 0;
- }
-
- #if 0
- while ((c = getc (in)) != EOF)
- #endif
- while ((rcount = read (in, locbuf, sizeof (locbuf))) != -1)
- {
- q = locbuf;
- while (rcount-- != 0)
- {
- c = *q++;
- if (c == 012)
- {
- *buf++ = 015;
- if (--m == 0)
- {
- Lfseen = TRUE;
- break;
- }
-
- }
-
- *buf++ = (char) c;
- if (--m == 0)
- break;
-
- } /* while (rcount-- != 0) */
-
- if (m == 0)
- break;
-
- } /* while ((rcount = read (in, locbuf, sizeof (locbuf)) != -1) */
-
- if (m == count)
- return 0;
- else
- while (--m >= 0)
- *buf++ = CPMEOF;
-
- return count;
- } /* static int filbuf (char *buf, int count) */
-
-
- /****************************************************************************
- * zfilbuf *
- * Fill <buf> with <count> chars. *
- ****************************************************************************/
-
- static int zfilbuf (char *buf, int count)
- {
- #ifndef ATARI
- if (eof (in))
- return (0);
- #endif
-
- return (read (in, buf, count));
- #if 0
- int c, m;
-
- m = count;
- while ((c = getc (in)) != EOF)
- {
- *buf++ = c;
- if (--m == 0)
- break;
-
- }
-
- return (count - m);
- #endif
- } /* static int zfilbuf (char *buf, int count) */
-
-
- /****************************************************************************
- * _vfile *
- * Print debugging message. *
- ****************************************************************************/
-
- void _vfile (char *f, ...)
- {
- va_list parms; /* -> variable arguments */
- char buf[128]; /* for text */
-
- va_start (parms, f);
- if (_Verbose > 2)
- {
- vsprintf (buf, f, parms);
- strcat (buf, "\n");
- (*_do_report) (2, buf); /* call reporter function */
- }
-
- va_end (parms);
- } /* void _vfile (char *f, ...) */
-
-
- /****************************************************************************
- * _say *
- * Report something unconditionally. *
- ****************************************************************************/
-
- void _say (char *f, ...)
- {
- va_list parms; /* -> variable arguments */
- char buf[128]; /* for text */
-
- va_start (parms, f);
- vsprintf (buf, f, parms);
- (*_do_report) (2, buf); /* call reporter function */
- va_end (parms);
- } /* void say (char *f, ...) */
-
-
- /****************************************************************************
- * readock *
- * Reads character(s) from receive channel. It attempts to read count *
- * characters (1 <= <count> <= 3). If it gets more than one, it is an *
- * error unless all are CAN (otherwise, only normal response is ACK, CAN *
- * or C). Only looks for one if Optiong, which signifies cbreak, not raw *
- * input. <timeout> is in tenths of seconds. *
- ****************************************************************************/
-
- static int readock (int timeout, int count)
- {
- int c, t;
- static unsigned char byt[5];
- time_t start; /* start time for timeout */
-
- if (Optiong)
- count = 1; /* Special hack for cbreak */
-
- t = timeout / 10;
- if (t < 2)
- t = 2;
-
- time (&start);
- if (_Verbose > 5)
- {
- _say ("Timeout=%d Calling alarm (%d) ", timeout, t);
- byt[1] = 0;
- }
-
- _no_carrier ();
- while (1)
- {
- c = _receive (byt, count);
- if (c != 0)
- break; /* got something */
-
- if (time (NULL) >= start + t)
- {
- _zperr_ ("TIMEOUT");
- return ZTIMEOUT;
- }
-
- }
-
- if (_Verbose > 5)
- _say ("ret cnt=%d %x %x\n", c, byt[0], byt[1]);
-
- if (c < 1)
- return ZTIMEOUT;
-
- if (c == 1)
- return (byt[0] & 0377);
- else
- while (c)
- if (byt[--c] != CAN)
- return ERROR;
-
- return CAN;
- } /* static int readock (int timeout, int count) */
-
-
- /****************************************************************************
- * readline *
- * Receive one control character with timeout. *
- ****************************************************************************/
-
- static int readline (int n)
- {
- return (readock (n, 1));
- } /* static int readline (int n) */
-
-
- /****************************************************************************
- * purgeline *
- * Flush input buffer. *
- ****************************************************************************/
-
- static void purgeline (void)
- {
- unsigned char c;
-
- while (_rdchk () > 0)
- _receive (&c, 1);
-
- #if 0
- while (_receive (&c, 1) > 0)
- ;
- #endif
-
- } /* static void purgeline (void) */
-
-
- /****************************************************************************
- * _canit *
- * Send cancel string to get the other end to shut up. *
- ****************************************************************************/
-
- void _canit (void)
- {
- int result;
- int count = 0;
- #ifdef DEBUGZ
- char buf[128];
- #endif
-
- static unsigned char canistr[] = { 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0 };
-
- _flushmo ();
- while (count != strlen ((char *) canistr))
- {
- while ((result = _send (canistr + count,
- strlen ((char *) canistr) - count)) == 0)
- ;
-
- count += result;
- #ifdef DEBUGZ
- sprintf (buf, "_canit: count = %d\r\n", count);
- _tout (buf);
- #endif
- }
-
- _flushmo ();
- } /* void _canit (void) */
-
-
- /****************************************************************************
- * _zperr_ *
- * Log an error. *
- ****************************************************************************/
-
- void _zperr_ (char *s, ...)
- {
- va_list parms;
- char buf0[128]; /* for report string */
- char buf1[128];
- char buf2[128];
-
- if (_Verbose <= 0)
- return;
-
- va_start (parms, s);
- sprintf (buf1, "Retry %d: ", _errors);
- vsprintf (buf2, s, parms);
- sprintf (buf0, "%s%s\n", buf1, buf2);
- (*_do_report) (2, buf0); /* call reporter function */
- va_end (parms);
- } /* void _zperr_ (char *s, ...) */
-
-
- /****************************************************************************
- * _zperr *
- * Default progress report function. *
- ****************************************************************************/
-
- void _zperr (int type, void *data)
- {
- switch (type)
- {
- case 0: /* filename */
- tprintf ("FILE: %s\n", data);
- break;
-
- case 1: /* bytes transferred */
- tprintf ("\r%7ld ", *((long *) data));
- break;
-
- case 2: /* other text */
- tprintf ("%s", data);
- break;
-
- case 3: /* end of transfer */
- tprintf ("%5d files transferred\n", *((int *) data));
- break;
-
- default:
- return;
- } /* switch (type) */
-
- } /* void _zperr (int type, void *data) */
-
-
- /****************************************************************************
- * _substr *
- * Searches for <token> in string <s>. Returns pointer to token within *
- * string if found, NULL otherwise. *
- ****************************************************************************/
-
- char *_substr (char *s, char *t)
- {
- char *ss,*tt;
-
- /* search for first char of token */
-
- for (ss = s; *s; s++)
- {
- if (*s == *t)
- {
- /* compare token with substring */
-
- for (ss = s, tt = t;;)
- {
- if (*tt == 0)
- return s;
-
- if (*ss++ != *tt++)
- break;
-
- }
-
- } /* if (*s == *t) */
-
- } /* for (ss = s; *s; s++) */
-
- return NULL;
- } /* char *_substr (char *s, char *t) */
-
-
- /****************************************************************************
- * getzrxinit *
- * Get the receiver's init parameters. *
- ****************************************************************************/
-
- static int getzrxinit (void)
- {
- int n;
- struct stat f;
-
- for (n = 10; --n >= 0;)
- {
- switch (_zgethdr (_Rxhdr, 1))
- {
- case ZCHALLENGE: /* Echo receiver's challenge numbr */
- _stohdr (_Rxpos);
- _zshhdr (ZACK, _Txhdr);
- continue;
-
- case ZCOMMAND: /* They didn't see out ZRQINIT */
- _stohdr (0L);
- _zshhdr (ZRQINIT, _Txhdr);
- continue;
-
- case ZRINIT:
- Rxflags = 0377 & _Rxhdr[ZF0];
- _Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
- _Zctlesc |= Rxflags & TESCCTL;
- Rxbuflen = (0377 & _Rxhdr[ZP0]) + ((0377 & _Rxhdr[ZP1]) << 8);
- _vfile ("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
- #if 0
- signal (SIGINT, SIG_IGN);
- #endif
-
- /* Override to force shorter frame length */
-
- if (Rxbuflen && (Rxbuflen > Tframlen) && (Tframlen >= 32))
- Rxbuflen = Tframlen;
-
- if (!Rxbuflen && (Tframlen >= 32) && (Tframlen <= 1024))
- Rxbuflen = Tframlen;
-
- _vfile ("Rxbuflen=%d", Rxbuflen);
-
- /*
- * If input is not a regular file, force ACK's each 1024
- * (A smarter strategey could be used here ...)
- */
-
- fstat (in, &f);
- if (((f.st_mode & S_IFMT) != S_IFREG) &&
- (Rxbuflen == 0 || Rxbuflen > 1024))
- Rxbuflen = 1024;
-
- _vfile ("Rxbuflen=%d", Rxbuflen);
-
- return (sendzsinit ());
-
- case ZCAN:
- case ZTIMEOUT:
- return ERROR;
-
- case ZRQINIT:
- if (_Rxhdr[ZF0] == ZCOMMAND)
- continue;
-
- default:
- _zshhdr (ZNAK, _Txhdr);
- continue;
- } /* switch (_zgethdr (_Rxhdr, 1)) */
-
- } /* for (n = 10; --n >= 0;) */
-
- return ERROR;
- } /* static int getzrxinit (void) */
-
-
- /****************************************************************************
- * sendzsinit *
- * Send send-init information. *
- ****************************************************************************/
-
- static int sendzsinit (void)
- {
- int c;
-
- if (Myattn[0] == '\0' && (!_Zctlesc || (Rxflags & TESCCTL)))
- return OK;
-
- _errors = 0;
- for (;;)
- {
- _stohdr (0L);
- if (_Zctlesc)
- {
- _Txhdr[ZF0] |= TESCCTL;
- _zshhdr (ZSINIT, _Txhdr);
- }
- else
- _zsbhdr (ZSINIT, _Txhdr);
-
- _zsdata (Myattn, 1 + strlen (Myattn), ZCRCW);
- c = _zgethdr (_Rxhdr, 1);
- switch (c)
- {
- case ZCAN:
- return ERROR;
-
- case ZACK:
- return OK;
-
- default:
- if (++_errors > 19)
- return ERROR;
-
- continue;
- } /* switch (c) */
-
- } /* for (;;) */
-
- } /* static int sendzsinit (void) */
-
-
- /****************************************************************************
- * zsendfile *
- * Send file name and related info. *
- ****************************************************************************/
-
- static int zsendfile (char *buf, int blen)
- {
- int c;
-
- for (;;)
- {
- _Txhdr[ZF0] = Lzconv; /* file conversion request */
- _Txhdr[ZF1] = _Lzmanag; /* file management request */
- if (Lskipnocor)
- _Txhdr[ZF1] |= ZMSKNOLOC;
-
- _Txhdr[ZF2] = Lztrans; /* file transport request */
- _Txhdr[ZF3] = 0;
- _zsbhdr (ZFILE, _Txhdr);
- _zsdata (buf, blen, ZCRCW);
-
- again:
- c = _zgethdr (_Rxhdr, 1);
- switch (c)
- {
- case ZRINIT:
- while ((c = readline (50)) > 0)
- if (c == ZPAD)
- {
- goto again;
- }
-
- /* **** FALL THRU TO **** */
-
- default:
- continue;
-
- case ZCAN:
- case ZTIMEOUT:
- case ZABORT:
- case ZFIN:
- return ERROR;
-
- case ZSKIP:
- close (in);
- return c;
-
- case ZRPOS:
- /*
- * Suppress zcrcw request otherwise triggered by
- * lastyunc==bytcnt
- */
-
- Lastsync = (bytcnt = _Txpos = _Rxpos) - 1;
- lseek (in, _Rxpos, 0);
- Dontread = FALSE;
- return zsendfdata ();
- } /* switch (c) */
-
- } /* for (;;) */
-
- } /* static int zsendfile (char *buf, int blen) */
-
-
- /****************************************************************************
- * zsendfdata *
- * Send the data in the file. *
- ****************************************************************************/
-
- static int zsendfdata (void)
- {
- int c, e, n;
- int newcnt;
- long tcount = 0;
- int junkcount; /* Counts garbage chars received by TX */
- static int tleft = 6; /* Counter for test mode */
- int sent_zm = FALSE; /* TRUE - sent ZMODEM string */
- if (_Baud_z > 300)
- blklen = 256;
-
- if (_Baud_z > 1200)
- blklen = 512;
-
- if (_Baud_z > 2400)
- blklen = KSIZE;
-
- if (Rxbuflen && blklen > Rxbuflen)
- blklen = Rxbuflen;
-
- if (blkopt && blklen > blkopt)
- blklen = blkopt;
-
- _vfile ("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
- _vfile ("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
- Lrxpos = 0;
- junkcount = 0;
- Beenhereb4 = FALSE;
-
- somemore:
- if (setjmp (intrjmp))
- {
- waitack:
- junkcount = 0;
- c = getinsync (0);
-
- gotack:
- switch (c)
- {
- default:
- case ZCAN:
- close (in);
- return ERROR;
-
- case ZSKIP:
- close (in);
- return c;
-
- case ZACK:
- case ZRPOS:
- break;
-
- case ZRINIT:
- return OK;
- } /* switch (c) */
-
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * _rdchk () returns non 0 if a character is available
- */
-
- while (_rdchk ())
- {
- switch (readline (1))
- {
- case CAN:
- case ZPAD:
- c = getinsync (1);
- goto gotack;
-
- case XOFF: /* Wait a while for an XON */
- case XOFF | 0200:
- readline(100);
- } /* switch (readline (1)) */
-
- } /* while (_rdchk ()) */
-
- } /* if (setjmp (intrjmp)) */
-
- #if 0
- signal (SIGINT, onintr);
- #endif
- newcnt = Rxbuflen;
- Txwcnt = 0;
- _stohdr (_Txpos);
- _zsbhdr (ZDATA, _Txhdr);
-
- /*
- * Special testing mode. This should force receiver to Attn,ZRPOS
- * many times. Each time the signal should be caught, causing the
- * file to be started over from the beginning.
- */
-
- if (Testattn)
- {
- if (--tleft)
- while (tcount < 20000)
- {
- _send ((unsigned char *) qbf, strlen (qbf));
- tcount += strlen (qbf);
- while (_rdchk ())
- {
- switch (readline (1))
- {
- case CAN:
- case ZPAD:
- goto waitack;
-
- case XOFF: /* Wait for XON */
- case XOFF | 0200:
- readline (100);
- } /* switch (readline (1)) */
-
- } /* while (_rdchk ()) */
-
- } /* while (tcount < 20000) */
-
- #if 0
- signal (SIGINT, SIG_IGN);
- #endif
- _canit ();
- sleep (3);
- purgeline ();
- printf ("\nTcount = %ld\n", tcount);
- if (tleft)
- {
- printf ("ERROR: Interrupts Not Caught\n");
- return (ERROR);
- }
-
- return (0);
- } /* if (Testattn) */
-
- do
- {
- if (Dontread)
- {
- n = Lastn;
- }
- else
- {
- n = zfilbuf (txbuf, blklen);
- Lastread = _Txpos;
- Lastn = n;
- }
-
- Dontread = FALSE;
- if (n < blklen)
- e = ZCRCE;
- else if (junkcount > 3)
- e = ZCRCW;
- else if (bytcnt == Lastsync)
- e = ZCRCW;
- else if (Rxbuflen && (newcnt -= n) <= 0)
- e = ZCRCW;
- else if (Txwindow && (Txwcnt += n) >= Txwspac)
- {
- Txwcnt = 0;
- e = ZCRCQ;
- }
- else
- e = ZCRCG;
-
- if (_Verbose > 1)
- {
- (*_do_report) (1, &_Txpos);
- if (!sent_zm)
- {
- sent_zm = TRUE;
- _say ("ZMODEM%s", _Crc32t ? " CRC-32" : "");
- }
-
- }
-
- _zsdata (txbuf, n, e);
- bytcnt = _Txpos += n;
- if (e == ZCRCW)
- goto waitack;
-
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * _rdchk () returns non 0 if a character is available
- */
-
- while (_rdchk ())
- {
- switch (readline (1))
- {
- case CAN:
- case ZPAD:
- c = getinsync (1);
- if (c == ZACK)
- break;
-
- /* zcrce - dinna wanna starta ping-pong game */
-
- _zsdata (txbuf, 0, ZCRCE);
- goto gotack;
-
- case XOFF: /* Wait a while for an XON */
- case XOFF | 0200:
- readline (100);
-
- default:
- ++junkcount;
- } /* switch (readline (1)) */
-
- } /* while (_rdchk ()) */
-
- if (Txwindow)
- {
- while ((tcount = _Txpos - Lrxpos) >= Txwindow)
- {
- _vfile ("%ld window >= %u", tcount, Txwindow);
- if (e != ZCRCQ)
- _zsdata (txbuf, 0, e = ZCRCQ);
-
- c = getinsync (1);
- if (c != ZACK)
- {
- _zsdata (txbuf, 0, ZCRCE);
- goto gotack;
- }
- }
-
- _vfile ("window = %ld", tcount);
- }
-
- } while (n == blklen);
-
- #if 0
- signal (SIGINT, SIG_IGN);
- #endif
-
- for (;;)
- {
- _stohdr (_Txpos);
- _zsbhdr (ZEOF, _Txhdr);
- switch (getinsync (0))
- {
- case ZACK:
- continue;
-
- case ZRPOS:
- goto somemore;
-
- case ZRINIT:
- return OK;
-
- case ZSKIP:
- close (in);
- return c;
-
- default:
- close (in);
- return ERROR;
- } /* switch (getinsync (0)) */
-
- } /* for (;;) */
-
- } /* static int zsendfdata (void) */
-
-
- /****************************************************************************
- * getinsync *
- * Respond to receiver's complaint, get back in sync with receiver. *
- ****************************************************************************/
-
- static int getinsync (int flag)
- {
- int c;
-
- for (;;)
- {
- if (Testattn)
- {
- printf ("\r\n\n\n***** Signal Caught *****\r\n");
- _Rxpos = 0;
- c = ZRPOS;
- }
- else
- c = _zgethdr (_Rxhdr, 0);
-
- switch (c)
- {
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case ZTIMEOUT:
- return ERROR;
-
- case ZRPOS:
- /* ************************************* */
- /* If sending to a modem buffer, you */
- /* might send a break at this point to */
- /* dump the modem's buffer. */
-
- if (Lastn >= 0 && Lastread == _Rxpos)
- {
- Dontread = TRUE;
- }
- else
- {
- #if 0
- clearerr (in); /* In case file EOF seen */
- #endif
- lseek (in, _Rxpos, 0);
- }
-
- bytcnt = Lrxpos = _Txpos = _Rxpos;
- if (Lastsync == _Rxpos)
- {
- if (++Beenhereb4 > 4)
- if (blklen > 256)
- blklen /= 2;
-
- }
-
- Lastsync = _Rxpos;
- return c;
-
- case ZACK:
- Lrxpos = _Rxpos;
- if (flag || _Txpos == _Rxpos)
- return ZACK;
-
- continue;
-
- case ZRINIT:
- case ZSKIP:
- close (in);
- return c;
-
- case ERROR:
- default:
- _zsbhdr (ZNAK, _Txhdr);
- continue;
- } /* switch (c) */
-
- } /* for (;;) */
-
- } /* static int getinsync (int flag) */
-
-
- /****************************************************************************
- * saybibi *
- * Say "bibi" to the receiver, try to do it cleanly. *
- ****************************************************************************/
-
- static void saybibi (void)
- {
- for (;;)
- {
- _stohdr (0L); /* CAF Was _zsbhdr - minor change */
- _zshhdr (ZFIN, _Txhdr); /* to make debugging easier */
- switch (_zgethdr (_Rxhdr, 0))
- {
- case ZFIN:
- _sendline ('O');
- _sendline ('O');
- _flushmo ();
-
- case ZCAN:
- case ZTIMEOUT:
- return;
- }
-
- }
-
- } /* static void saybibi (void) */
-
-
- /****************************************************************************
- * _bttyout *
- * Local screen character display function. *
- ****************************************************************************/
-
- void _bttyout (int c)
- {
- char str[2]; /* for making string */
-
- if (_Verbose)
- {
- str[0] = (char) c;
- str[1] = '\0';
- _say (str);
- }
-
- } /* void _bttyout (int c) */
-
-
- /****************************************************************************
- * zsendcmd *
- * Send command and related info. *
- ****************************************************************************/
-
- static int zsendcmd (char *buf, int blen)
- {
- int c;
- long cmdnum;
-
- cmdnum = getpid ();
- _errors = 0;
- for (;;)
- {
- _stohdr (cmdnum);
- _Txhdr[ZF0] = (char) Cmdack1;
- _zsbhdr (ZCOMMAND, _Txhdr);
- _zsdata (buf, blen, ZCRCW);
-
- listen:
- _Rxtimeout = 100; /* Ten second wait for resp. */
- c = _zgethdr (_Rxhdr, 1);
-
- switch (c)
- {
- case ZRINIT:
- goto listen; /* CAF 8-21-87 */
-
- case ERROR:
- case ZTIMEOUT:
- if (++_errors > Cmdtries)
- return ERROR;
-
- continue;
-
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case ZSKIP:
- case ZRPOS:
- return ERROR;
-
- default:
- if (++_errors > 20)
- return ERROR;
-
- continue;
-
- case ZCOMPL:
- Exitcode = (int) _Rxpos;
- saybibi ();
- return OK;
- } /* switch (c) */
-
- } /* for (;;) */
-
- } /* static int zsendcmd (char *buf, int blen) */
-
-
- /****************************************************************************
- * chkinvok *
- * Set chosen protocol. *
- ****************************************************************************/
-
- static void chkinvok (char protocol)
- {
- if (protocol == 'y')
- {
- _Nozmodem = TRUE;
- blklen = KSIZE;
- }
-
- if (protocol == 'x')
- {
- Modem2 = TRUE;
- }
-
- } /* static void chkinvok (char protocol) */
- /* End of sz.c */
-